#pragma once

#include <iostream>
#include <string>
#include <sys/epoll.h>
#include <unordered_map>
#include <cstdlib>

#define SIZE 128
#define NUM 64
class Event;
class Reactor;
typedef int (*callback_t)(Event *ev);

class Event
{
public:
    int sock; // 对应文件描述符
    std::string inbuffer;
    std::string outbuffer;
    callback_t recver;
    callback_t sender;
    callback_t errorer;

    Reactor *R;

public:
    Event()
    {
        sock = -1;
        recver = nullptr;
        sender = nullptr;
        errorer = nullptr;
        R = nullptr;
    }
    void RegisterCallback(callback_t _recver, callback_t _sender, callback_t _errorer)
    {
        recver = _recver;
        sender = _sender;
        errorer = _errorer;
    }
    ~Event()
    {}
};

class Reactor
{
private:
    int epfd;
    std::unordered_map<int, Event *> events;

public:
    Reactor() : epfd(-1) {}
    void InitReactor()
    {
        epfd = epoll_create(SIZE);
        if (epfd < 0)
        {
            std::cerr << "epoll_create error" << std::endl;
            exit(2);
        }
        std::cout << "InitReactor success" << std::endl;
    }
    bool InsertEvent(Event *evp, uint32_t evs)
    {
        struct epoll_event ev;
        ev.events = evs;
        ev.data.fd = evp->sock;
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, evp->sock, &ev) < 0)
        {
            std::cerr << "epoll_ctl add event failed" << std::endl;
            return false;
        }

        events.insert({evp->sock, evp});
        return true;
    }
    void DeleteEvent(Event *evp)
    {
        int sock = evp->sock;
        epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
        auto iter = events.find(sock);
        if (iter != events.end())
        {
            events.erase(iter);
        }
    }

    bool EnableRW(int sock,bool enbread,bool enbwrite)
    {
        struct epoll_event ev;
        ev.data.fd = sock;
        ev.events = EPOLLET | (enbread?EPOLLIN:0) |(enbwrite?EPOLLOUT:0);
        if(epoll_ctl(epfd,EPOLL_CTL_MOD,sock,&ev)<0)
        {
            std::cerr<<"epoll_ctl mod event failed"<<std::endl;
        }
        return false;
    }
    void Dispather(int timeout)
    {
        struct epoll_event revs[NUM];
        int n = epoll_wait(epfd, revs, NUM, timeout);

        for (int i = 0; i < n; i++)
        {
            int sock = revs[i].data.fd;
            uint32_t revents = revs[i].events;
            //差错处理，所有错误问题让io函数去解决
            if (revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            if (revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);

            if (revents & EPOLLIN)
            {
                if (events[sock]->recver)
                    events[sock]->recver(events[sock]);
            }
            if (revents & EPOLLOUT)
            {
                if (events[sock]->sender)
                    events[sock]->sender(events[sock]);
            }
        }
    }
    ~Reactor() {}
};
